home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / sys5 / iscwmpst.z / iscwmpst / tcp / util / udbm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-29  |  17.5 KB  |  735 lines

  1. /* User Data Base Manager */
  2.  
  3. static char  rcsid[] = "@(#) $Header: udbm.c,v 1.11 91/10/25 14:21:28 deyke Exp $";
  4.  
  5. #define DEBUG           0
  6.  
  7. #define _HPUX_SOURCE    1
  8.  
  9. #include <sys/types.h>
  10.  
  11. #include <ctype.h>
  12. #include <errno.h>
  13. #include <fcntl.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <sys/stat.h>
  18.  
  19. #ifdef __TURBOC__
  20.  
  21. #include <alloc.h>
  22. #include <dos.h>
  23. #include <io.h>
  24.  
  25. struct utsname {
  26.   char  nodename[16];
  27. };
  28.  
  29. struct passwd {
  30.   char  *pw_name;
  31.   char  *pw_gecos;
  32. };
  33.  
  34. #else
  35.  
  36. #include <pwd.h>
  37. #include <sys/utsname.h>
  38. #include <unistd.h>
  39.  
  40. #endif
  41.  
  42. #if (defined(__STDC__) || defined(__TURBOC__))
  43. #define __ARGS(x)       x
  44. #else
  45. #define __ARGS(x)       ()
  46. #define const
  47. #endif
  48.  
  49. struct user {
  50.   struct user *next;
  51.   const char *call;
  52.   const char *name;
  53.   const char *street;
  54.   const char *city;
  55.   const char *qth;
  56.   const char *phone;
  57.   const char *mail;
  58.   char alias;
  59. };
  60.  
  61. #define NUM_USERS 2503
  62.  
  63. #if DEBUG
  64. static char usersfile[] = "users";
  65. static char userstemp[] = "users.tmp";
  66. static char indexfile[] = "index";
  67. static char passfile[]  = "passwd";
  68. static char passtemp[]  = "ptmp";
  69. static char aliasfile[] = "aliases";
  70. static char aliastemp[] = "aliases.tmp";
  71. #else
  72. static char usersfile[] = "/usr/local/lib/users";
  73. static char userstemp[] = "/usr/local/lib/users.tmp";
  74. static char indexfile[] = "/users/bbs/index";
  75. static char passfile[]  = "/etc/passwd";
  76. static char passtemp[]  = "/etc/ptmp";
  77. static char aliasfile[] = "/usr/lib/aliases";
  78. static char aliastemp[] = "/usr/lib/aliases.tmp";
  79. #endif
  80.  
  81. static const char *lockfile;
  82. static const char *null_string = "";
  83. static long  heapsize;
  84. static struct user *users[NUM_USERS];
  85. static struct user null_user;
  86. static struct utsname uts_name;
  87.  
  88. int uname __ARGS((struct utsname *name));
  89. struct passwd *getpwent __ARGS((void));
  90. void endpwent __ARGS((void));
  91. int putpwent __ARGS((struct passwd *p, FILE *f));
  92. static void terminate __ARGS((const char *s));
  93. static void *allocate __ARGS((size_t size));
  94. static int calc_crc __ARGS((const char *str));
  95. static const char *strsave __ARGS((const char *s));
  96. static char *strlwc __ARGS((char *s));
  97. static char *rmspaces __ARGS((char *s));
  98. static char *strtrim __ARGS((char *s));
  99. static int is_call __ARGS((const char *s));
  100. static int is_qth __ARGS((const char *s));
  101. static int is_phone __ARGS((const char *s));
  102. static int is_mail __ARGS((const char *s));
  103. static int join __ARGS((const char **s1, const char **s2));
  104. static struct user *getup __ARGS((const char *call, int create));
  105. static FILE *fopenexcl __ARGS((const char *path));
  106. static void output_line __ARGS((const struct user *up, FILE *fp));
  107. static int fixusers __ARGS((void));
  108. static void fixpasswd __ARGS((void));
  109. static void fixaliases __ARGS((void));
  110. int main __ARGS((void));
  111.  
  112. /*---------------------------------------------------------------------------*/
  113.  
  114. #ifdef __TURBOC__
  115.  
  116. unsigned  _stklen = 10240;
  117.  
  118. int  uname(struct utsname *name)
  119. {
  120.   strcpy(name->nodename, "db0sao");
  121.   return 0;
  122. }
  123.  
  124. struct passwd *getpwent(void)
  125. {
  126.   return NULL;
  127. }
  128.  
  129. void endpwent(void)
  130. {
  131. }
  132.  
  133. int  putpwent(struct passwd *p, FILE *f)
  134. {
  135.   return 0;
  136. }
  137.  
  138. #endif
  139.  
  140. /*---------------------------------------------------------------------------*/
  141.  
  142. static void terminate(s)
  143. const char *s;
  144. {
  145.   perror(s);
  146.   if (lockfile) unlink(lockfile);
  147.   exit(1);
  148. }
  149.  
  150. /*---------------------------------------------------------------------------*/
  151.  
  152. #define uchar(c)  ((unsigned char) (c))
  153.  
  154. /*---------------------------------------------------------------------------*/
  155.  
  156. static void *allocate(size)
  157. size_t size;
  158. {
  159.  
  160.   static char  *freespace;
  161.   static size_t allocsize = 64*1024-2;
  162.   static size_t freesize;
  163.   void * p;
  164.  
  165.   if (size & 1) size++;
  166.   if (size > freesize) {
  167.     for (; ; ) {
  168. #ifdef __TURBOC__
  169.       fprintf(stderr, "size = %u coreleft = %lu allocsize = %u\n",
  170.           size, coreleft(), allocsize);
  171. #endif
  172.       if (size > allocsize) {
  173.     errno = ENOMEM;
  174.     terminate("allocate()");
  175.       }
  176.       if ((freespace = malloc(allocsize)) != NULL) {
  177.     freesize = allocsize;
  178.     heapsize += allocsize;
  179.     break;
  180.       }
  181.       allocsize >>= 1;
  182.     }
  183.   }
  184.   p = freespace;
  185.   freespace += size;
  186.   freesize -= size;
  187.   return p;
  188. }
  189.  
  190. /*---------------------------------------------------------------------------*/
  191.  
  192. /* Calculate crc16 for a null terminated string (used for hashing) */
  193.  
  194. static int  calc_crc(str)
  195. const char *str;
  196. {
  197.  
  198.   static const int crc_table[] = {
  199.     0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
  200.     0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
  201.     0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
  202.     0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
  203.     0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
  204.     0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
  205.     0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
  206.     0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
  207.     0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
  208.     0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
  209.     0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
  210.     0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
  211.     0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
  212.     0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
  213.     0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
  214.     0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
  215.     0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
  216.     0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
  217.     0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
  218.     0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
  219.     0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
  220.     0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
  221.     0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
  222.     0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
  223.     0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
  224.     0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
  225.     0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
  226.     0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
  227.     0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
  228.     0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
  229.     0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
  230.     0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
  231.   };
  232.  
  233.   int  crc;
  234.  
  235.   crc = 0;
  236.   while (*str)
  237.     crc = ((crc >> 8) & 0xff) ^ crc_table[(crc ^ *str++) & 0xff];
  238.   return crc;
  239. }
  240.  
  241. /*---------------------------------------------------------------------------*/
  242.  
  243. static const char *strsave(s)
  244. const char *s;
  245. {
  246.  
  247. #define NUM_STRINGS 4999
  248.  
  249.   struct strings {
  250.     struct strings *next;
  251.     char  s[1];
  252.   };
  253.  
  254.   int  hash;
  255.   static struct strings *strings[NUM_STRINGS];
  256.   struct strings *p;
  257.  
  258.   if (!*s) return null_string;
  259.   for (p = strings[hash = ((calc_crc(s) & 0x7fff) % NUM_STRINGS)];
  260.        p && strcmp(s, p->s);
  261.        p = p->next)
  262.     ;
  263.   if (!p) {
  264.     p = allocate(sizeof(struct strings *) + strlen(s) + 1);
  265.     strcpy(p->s, s);
  266.     p->next = strings[hash];
  267.     strings[hash] = p;
  268.   }
  269.   return p->s;
  270. }
  271.  
  272. /*---------------------------------------------------------------------------*/
  273.  
  274. static char  *strlwc(s)
  275. char  *s;
  276. {
  277.   char  *p;
  278.  
  279.   for (p = s; (*p = tolower(uchar(*p))) != 0; p++) ;
  280.   return s;
  281. }
  282.  
  283. /*---------------------------------------------------------------------------*/
  284.  
  285. static char  *rmspaces(s)
  286. char  *s;
  287. {
  288.   char  *f, *t;
  289.  
  290.   for (f = t = s; *f; f++)
  291.     if (*f != ' ') *t++ = *f;
  292.   *t = '\0';
  293.   return s;
  294. }
  295.  
  296. /*---------------------------------------------------------------------------*/
  297.  
  298. static char  *strtrim(s)
  299. char  *s;
  300. {
  301.   char  *p;
  302.  
  303.   for (p = s; *p; p++) ;
  304.   while (--p >= s && *p == ' ') ;
  305.   p[1] = '\0';
  306.   return s;
  307. }
  308.  
  309. /*---------------------------------------------------------------------------*/
  310.  
  311. static int  is_call(s)
  312. const char *s;
  313. {
  314.   int  d, l;
  315.  
  316.   l = strlen(s);
  317.   if (l < 4 || l > 6) return 0;
  318.   if (!isalpha(uchar(s[l-1]))) return 0;
  319.   for (d = 0; *s; s++) {
  320.     if (!isalnum(uchar(*s))) return 0;
  321.     if (isdigit(uchar(*s))) d++;
  322.   }
  323.   return (d >= 1 && d <= 2);
  324. }
  325.  
  326. /*---------------------------------------------------------------------------*/
  327.  
  328. static int  is_qth(s)
  329. const char *s;
  330. {
  331.   switch (strlen(s)) {
  332.   case 5:
  333.     if ((s[0] >= 'A' && s[0] <= 'Z' || s[0] >= 'a' && s[0] <= 'z') &&
  334.     (s[1] >= 'A' && s[1] <= 'Z' || s[1] >= 'a' && s[1] <= 'z') &&
  335.     (s[2] >= '0' && s[2] <= '8'                              ) &&
  336.     (s[3] >= '0' && s[3] <= '9'                              ) &&
  337.     (s[4] >= 'A' && s[4] <= 'J' || s[4] >= 'a' && s[4] <= 'j') &&
  338.      s[4] != 'I' && s[4] != 'i')
  339.       return 1;
  340.     break;
  341.   case 6:
  342.     if ((s[0] >= 'A' && s[0] <= 'R' || s[0] >= 'a' && s[0] <= 'r') &&
  343.     (s[1] >= 'A' && s[1] <= 'R' || s[1] >= 'a' && s[1] <= 'r') &&
  344.     (s[2] >= '0' && s[2] <= '9'                              ) &&
  345.     (s[3] >= '0' && s[3] <= '9'                              ) &&
  346.     (s[4] >= 'A' && s[4] <= 'X' || s[4] >= 'a' && s[4] <= 'x') &&
  347.     (s[5] >= 'A' && s[5] <= 'X' || s[5] >= 'a' && s[5] <= 'x'))
  348.       return 1;
  349.     break;
  350.   }
  351.   return 0;
  352. }
  353.  
  354. /*---------------------------------------------------------------------------*/
  355.  
  356. static int  is_phone(s)
  357. const char *s;
  358. {
  359.   int  slash;
  360.  
  361.   for (slash = 0; *s; s++)
  362.     if (*s == '/')
  363.       slash++;
  364.     else if (!isdigit(uchar(*s)))
  365.       return 0;
  366.   return (slash == 1);
  367. }
  368.  
  369. /*---------------------------------------------------------------------------*/
  370.  
  371. static int  is_mail(s)
  372. const char *s;
  373. {
  374.   return (int) (strchr(s, '@') != NULL);
  375. }
  376.  
  377. /*---------------------------------------------------------------------------*/
  378.  
  379. static int  join(s1, s2)
  380. const char **s1, **s2;
  381. {
  382.   if (s1 == s2) return 0;
  383.   if (*s1 == null_string || strstr(*s2, *s1)) {
  384.     *s1 = *s2;
  385.     return 0;
  386.   }
  387.   if (*s2 == null_string || strstr(*s1, *s2)) {
  388.     *s2 = *s1;
  389.     return 0;
  390.   }
  391.   return 1;
  392. }
  393.  
  394. /*---------------------------------------------------------------------------*/
  395.  
  396. static struct user *getup(call, create)
  397. const char *call;
  398. int  create;
  399. {
  400.  
  401.   int  hash;
  402.   struct user *up;
  403.  
  404.   for (up = users[hash = ((calc_crc(call) & 0x7fff) % NUM_USERS)];
  405.        up && strcmp(call, up->call);
  406.        up = up->next)
  407.     ;
  408.   if (create && !up) {
  409.     up = allocate(sizeof(*up));
  410.     *up = null_user;
  411.     up->call = strsave(call);
  412.     up->next = users[hash];
  413.     users[hash] = up;
  414.   }
  415.   return up;
  416. }
  417.  
  418. /*---------------------------------------------------------------------------*/
  419.  
  420. static FILE *fopenexcl(path)
  421. const char *path;
  422. {
  423.  
  424.   FILE * fp;
  425.   int  fd, try;
  426.  
  427.   for (try = 1; ; try++) {
  428.     if ((fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0644)) >= 0) break;
  429.     if (try >= 10) terminate(path);
  430.     sleep(try);
  431.   }
  432.   lockfile = path;
  433.   fp = fdopen(fd, "w");
  434.   if (!fp) terminate(path);
  435.   return fp;
  436. }
  437.  
  438. /*---------------------------------------------------------------------------*/
  439.  
  440. static void output_line(up, fp)
  441. const struct user *up;
  442. FILE *fp;
  443. {
  444.  
  445. #define append(s)                    \
  446.   if (*(s)) {                        \
  447.     if (*line) {                     \
  448.       *t++ = ',';                    \
  449.       *t++ = ' ';                    \
  450.     }                                \
  451.     for (f = (s); *f; *t++ = *f++) ; \
  452.   }
  453.  
  454.   char line[1024];
  455.   const char *f;
  456.   char *t;
  457.  
  458.   t = line;
  459.   *t = '\0';
  460.   append(up->call);
  461.   append(up->name);
  462.   append(up->street);
  463.   append(up->city);
  464.   append(up->qth);
  465.   append(up->phone);
  466.   append(up->mail);
  467.   *t = '\0';
  468.   fputs(line, fp);
  469.   putc('\n', fp);
  470. }
  471.  
  472. /*---------------------------------------------------------------------------*/
  473.  
  474. static int  fixusers()
  475. {
  476.  
  477. #define NF 20
  478.  
  479. #define LEN_BID     12
  480. #define LEN_SUBJECT 80
  481. #define LEN_TO      8
  482. #define LEN_AT      8
  483. #define LEN_FROM    8
  484.  
  485.   struct index {
  486.     long  size;
  487.     long  date;
  488.     int  mesg;
  489.     char  bid[LEN_BID+1];
  490.     char  lifetime_h;
  491.     char  subject[LEN_SUBJECT+1];
  492.     char  lifetime_l;
  493.     char  to[LEN_TO+1];
  494.     char  at[LEN_AT+1];
  495.     char  from[LEN_FROM+1];
  496.     char  deleted;
  497.   };
  498.  
  499.   FILE *fpi, *fpo;
  500.   char  *f, *t;
  501.   char  *field[NF];
  502.   char  line[1024], orig_line[1024], mybbs[1024];
  503.   int  errors = 0;
  504.   int  i, nf, timestamp;
  505.   struct index index;
  506.   struct user *up;
  507.   struct user user;
  508.  
  509.   if (!(fpi = fopen(usersfile, "r"))) terminate(usersfile);
  510.   fpo = fopenexcl(userstemp);
  511.   while (fgets(line, sizeof(line), fpi)) {
  512.     for (f = line; *f; f++)
  513.       if (isspace(uchar(*f))) *f = ' ';
  514.     for (t = f = line; *f; f++)
  515.       if (*f != ' ' || f[1] != ' ') *t++ = *f;
  516.     if (t > line && t[-1] == ' ') t--;
  517.     *t = '\0';
  518.     strcpy(orig_line, line);
  519.     f = line;
  520.     memset(field, 0 , sizeof(field));
  521.     nf = 0;
  522.     user = null_user;
  523.     for (; ; ) {
  524.       while (*f && (*f == ' ' || *f == ',')) f++;
  525.       if (!*f) break;
  526.       field[nf++] = f;
  527.       f = strchr(f, ',');
  528.       if (f)
  529.     *f++ = '\0';
  530.       else
  531.     f = "";
  532.       strtrim(field[nf-1]);
  533.     }
  534.     if (!nf) continue;
  535.     for (i = 0; i < NF; i++)
  536.       if (field[i]) {
  537.     if (!*user.call && is_call(field[i])) {
  538.       user.call = strsave(strlwc(field[i]));
  539.       field[i] = NULL;
  540.       nf--;
  541.     } else if (!*user.qth && is_qth(field[i])) {
  542.       user.qth = strsave(strlwc(field[i]));
  543.       field[i] = NULL;
  544.       nf--;
  545.     } else if (!*user.phone && is_phone(field[i])) {
  546.       user.phone = strsave(field[i]);
  547.       field[i] = NULL;
  548.       nf--;
  549.     } else if (!*user.mail && is_mail(field[i])) {
  550.       user.mail = strsave(strlwc(rmspaces(field[i])));
  551.       field[i] = NULL;
  552.       nf--;
  553.     }
  554.       }
  555.     if (nf)
  556.       for (i = 0; i < NF; i++)
  557.     if (field[i]) {
  558.       user.name = strsave(field[i]);
  559.       field[i] = NULL;
  560.       nf--;
  561.       break;
  562.     }
  563.     if (nf >= 2)
  564.       for (i = 0; i < NF; i++)
  565.     if (field[i]) {
  566.       user.street = strsave(field[i]);
  567.       field[i] = NULL;
  568.       nf--;
  569.       break;
  570.     }
  571.     if (nf)
  572.       for (i = 0; i < NF; i++)
  573.     if (field[i]) {
  574.       user.city = strsave(field[i]);
  575.       field[i] = NULL;
  576.       nf--;
  577.       break;
  578.     }
  579.     if (nf) {
  580.       errors++;
  581.       fprintf(stderr, "***** Too many fields *****\n%s\n\n", orig_line);
  582.       fputs(orig_line, fpo);
  583.       putc('\n', fpo);
  584.       continue;
  585.     }
  586.     if (!*user.call) {
  587.       fputs(orig_line, fpo);
  588.       putc('\n', fpo);
  589.       continue;
  590.     }
  591.     up = getup(user.call, 1);
  592.     if (join(&up->name, &user.name)     |
  593.     join(&up->street, &user.street) |
  594.     join(&up->city, &user.city)     |
  595.     join(&up->qth, &user.qth)       |
  596.     join(&up->phone, &user.phone)   |
  597.     join(&up->mail, &user.mail)) {
  598.       errors++;
  599.       fprintf(stderr, "***** Join failed *****\n%s\n\n", orig_line);
  600.       output_line(&user, fpo);
  601.     }
  602.   }
  603.   fclose(fpi);
  604.  
  605.   if ((fpi = fopen(indexfile, "r")) != NULL) {
  606.     while (fread((char *) &index, sizeof(index), 1, fpi))
  607.       if (index.to[0] == 'M' && index.to[1] == '\0'              &&
  608.       !strcmp(index.at, "THEBOX")                            &&
  609.       is_call(index.from)                                    &&
  610.       sscanf(index.subject, "%s %d", mybbs, ×tamp) == 2 &&
  611.       is_call(mybbs)) {
  612.     up = getup(strlwc(index.from), 1);
  613.     *line = '@';
  614.     strcpy(line+1, strlwc(mybbs));
  615.     up->mail = strsave(line);
  616.       }
  617.     fclose(fpi);
  618.   }
  619.  
  620.   if (is_call(uts_name.nodename)) {
  621.     up = getup(uts_name.nodename, 1);
  622.     *line = '@';
  623.     strcpy(line+1, up->call);
  624.     up->mail = strsave(line);
  625.   }
  626.  
  627.   for (i = 0; i < NUM_USERS; i++)
  628.     for (up = users[i]; up; up = up->next) output_line(up, fpo);
  629.   fclose(fpo);
  630.  
  631. #ifdef __TURBOC__
  632.   unlink(usersfile);
  633. #endif
  634.   if (rename(userstemp, usersfile)) terminate(usersfile);
  635.   lockfile = NULL;
  636.   return errors;
  637. }
  638.  
  639. /*---------------------------------------------------------------------------*/
  640.  
  641. static void fixpasswd()
  642. {
  643.  
  644.   FILE * fp;
  645.   struct passwd *pp;
  646.   struct user *up;
  647.  
  648.   fp = fopenexcl(passtemp);
  649.   while ((pp = getpwent()) != NULL) {
  650.     if (is_call(pp->pw_name) && (up = getup(pp->pw_name, 0)) != NULL)
  651.       pp->pw_gecos = (char *) up->name;
  652.     putpwent(pp, fp);
  653.   }
  654.   endpwent();
  655.   fclose(fp);
  656. #ifdef __TURBOC__
  657.   unlink(passfile);
  658. #endif
  659.   if (rename(passtemp, passfile)) terminate(passfile);
  660.   lockfile = NULL;
  661. }
  662.  
  663. /*---------------------------------------------------------------------------*/
  664.  
  665. static void fixaliases()
  666. {
  667.  
  668.   FILE * fpi, *fpo;
  669.   char  *p;
  670.   char  line[1024];
  671.   int  i;
  672.   struct user *up;
  673.  
  674.   if (!(fpi = fopen(aliasfile, "r"))) terminate(aliasfile);
  675.   fpo = fopenexcl(aliastemp);
  676.   while (fgets(line, sizeof(line), fpi)) {
  677.     if (!strncmp(line, "# Generated", 11)) break;
  678.     fputs(line, fpo);
  679.     if (isspace(uchar(*line))) continue;
  680.     if ((p = strchr(line, '#')) != NULL) *p = '\0';
  681.     if (!(p = strchr(line, ':'))) continue;
  682.     while (--p >= line && isspace(uchar(*p))) ;
  683.     p[1] = '\0';
  684.     if ((up = getup(line, 0)) != NULL) up->alias = 1;
  685.   }
  686.   fclose(fpi);
  687.   fputs("# Generated aliases\n", fpo);
  688.   for (i = 0; i < NUM_USERS; i++)
  689.     for (up = users[i]; up; up = up->next)
  690.       if (!up->alias && *up->mail)
  691.     if (*up->mail == '@')
  692.       fprintf(fpo, "%s\t\t: %s%s\n", up->call, up->call, up->mail);
  693.     else
  694.       fprintf(fpo, "%s\t\t: %s\n", up->call, up->mail);
  695.   fclose(fpo);
  696. #ifdef __TURBOC__
  697.   unlink(aliasfile);
  698. #endif
  699.   if (rename(aliastemp, aliasfile)) terminate(aliasfile);
  700.   lockfile = NULL;
  701. }
  702.  
  703. /*---------------------------------------------------------------------------*/
  704.  
  705. int  main()
  706. {
  707.  
  708.   null_user.next = 0;
  709.   null_user.call = null_string;
  710.   null_user.name = null_string;
  711.   null_user.street = null_string;
  712.   null_user.city = null_string;
  713.   null_user.qth = null_string;
  714.   null_user.phone = null_string;
  715.   null_user.mail = null_string;
  716.   null_user.alias = 0;
  717.  
  718.   umask(022);
  719.   uname(&uts_name);
  720.   if (!fixusers()) {
  721.     fixpasswd();
  722.     fixaliases();
  723. #if (!DEBUG && !defined(__TURBOC__))
  724.     system("exec /usr/bin/newaliases >/dev/null 2>&1");
  725. #endif
  726.   }
  727.  
  728. #if DEBUG
  729.   fprintf(stderr, "Total heap size = %ld Bytes\n", heapsize);
  730. #endif
  731.  
  732.   return 0;
  733. }
  734.  
  735.